#include "env_checker.h"
#include <windows.h>
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "logger.h"
#include "utils.h"
using namespace std;
using namespace cv;

#define TEST_SLEF (0)
static void print_env_info(struct env_info & info)
{
    LOG(INFO)<< "left_plate = " << info.left_plate;
    LOG(INFO)<< "right_plate = " << info.right_plate;
    LOG(INFO)<< "left_line = " << info.left_line;
    LOG(INFO)<< "right_line = " << info.right_line;
    LOG(INFO)<< "left_back_line = " << info.left_back_line;
    LOG(INFO)<< "right_back_line = " << info.right_back_line;
    LOG(INFO)<< "people = " << info.people;
}

static Rect read_rect_ini(char *pFile,char *pRectName)
{
    int x = GetPrivateProfileIntA(pRectName, "x", -1, pFile);
    int y = GetPrivateProfileIntA(pRectName, "y", -1, pFile);
    int w = GetPrivateProfileIntA(pRectName, "w", -1, pFile);
    int h = GetPrivateProfileIntA(pRectName, "h", -1, pFile);
    return Rect(x, y, w, h);
}

static int read_points_ini(char *pFile, char *pPointsName, std::vector<cv::Point>& pts ,int num)
{
    //获取str
    char buffer[1024] = {};
    GetPrivateProfileStringA(pPointsName, "points_str", "", buffer, sizeof(buffer) / sizeof(char), pFile);
    string pointsStr = string(buffer);
    //LOG(INFO) << "pointsStr = " << pointsStr << endl;

    //判断个数
    auto tmpElements = stringSplit(pointsStr, ',');
    if (tmpElements.size() / 2 != num) {
        LOG(ERROR) << "tmpElements.size()/2 = " << tmpElements.size()/2 << "v.s. num = "  << num <<endl;
        return -1;
    }

    //放入pts
    for (int i = 0; i < num; i++) {
        Point tmp = Point(stoi(tmpElements[i*2]), stoi(tmpElements[i * 2+1]));
        pts.push_back(tmp);
    }

    return 0;
}


inline void rect2pts(Rect rect, std::vector<cv::Point>& pts)
{
    pts.push_back(Point(rect.x, rect.y));
    pts.push_back(Point(rect.x, rect.y + rect.height));
    pts.push_back(Point(rect.x+ rect.width, rect.y + rect.height));
    pts.push_back(Point(rect.x + rect.width, rect.y));
}

inline void print_pts(std::vector<cv::Point> points, std::string pts_name)
{
    int num = 0;
    LOG(INFO) << "pts_name = " << pts_name << endl;
    for (auto& point : points) {

        LOG(INFO) << "point num " << num++ << " " << point << endl;
    }
}

Env_checker::Env_checker()
{

}

Env_checker::~Env_checker()
{

}

int Env_checker::init()
{
#if 1
    int nRet = hk_sdk.init();
    if (nRet) {
        LOG(ERROR) << "hk_sdk init err" << endl;
        return -1;
    }
#endif

    char file_ini[64] = CONFIG_FILE_PATH;
    char rect_name[][64] = {"left_rect","right_rect", "left_line", "right_line","left_back_line", "right_back_line","people_left_rect","people_right_rect"};
    left_rect =  read_rect_ini(file_ini, rect_name[0]);
    LOG(INFO) << "left_rect = "<<left_rect << endl;

    right_rect = read_rect_ini(file_ini, rect_name[1]);
    LOG(INFO) << "right_rect = " << right_rect << endl;

    if (-1 == read_points_ini(file_ini, rect_name[2], left_line_pts, 4)) {
        LOG(ERROR) << "read  " << rect_name[2]<< "error" << endl;
        return -1;
    }
    print_pts(left_line_pts, rect_name[2]);


    if (-1 == read_points_ini(file_ini, rect_name[3], right_line_pts, 4)) {
        LOG(ERROR) << "read  " << rect_name[3] << "error" << endl;
        return -1;
    }
    print_pts(right_line_pts, rect_name[3]);

    if (-1 == read_points_ini(file_ini, rect_name[4], left_back_line_pts, 4)) {
        LOG(ERROR) << "read  " << rect_name[4] << "error" << endl;
        return -1;
    }
    print_pts(left_back_line_pts, rect_name[4]);

    if (-1 == read_points_ini(file_ini, rect_name[5], right_back_line_pts, 4)) {
        LOG(ERROR) << "read  " << rect_name[5] << "error" << endl;
        return -1;
    }
    print_pts(right_back_line_pts, rect_name[5]);

    people_left_rect = read_rect_ini(file_ini, rect_name[6]);
    LOG(INFO) << "people_left_rect = " << people_left_rect << endl;


    people_right_rect = read_rect_ini(file_ini, rect_name[7]);
    LOG(INFO) << "people_right_rect = " << people_right_rect << endl;

    plate_detector.init();
    line_detector.init();
    return 0;
}

int Env_checker::check_info(int nSide)
{

    LOG(INFO) << "do mSide = " << nSide << std::endl;
    //拿imgs
    Mat left_cam_img, right_cam_img;
    hk_sdk.get_last_img(left_cam_img, ENV_SIDE_A);
    hk_sdk.get_last_img(right_cam_img, ENV_SIDE_B);

    if (left_cam_img.empty() || right_cam_img.empty()) {
        LOG(ERROR) << "left_cam_img.empty() = " << left_cam_img.empty() << std::endl;
        LOG(ERROR) << "right_cam_img.empty() = " << right_cam_img.empty() << std::endl;
        set_info_img_err();
        return -1;
    }

#if 1
    //存本地
    static int num = 0;
    char path[64] = {};
    sprintf_s(path, sizeof(path), "./env_save/left_%d.jpg",num);
    cv::imwrite(path, left_cam_img);
    sprintf_s(path, sizeof(path), "./env_save/right_%d.jpg", num);
    cv::imwrite(path, right_cam_img);
    num++;
#endif
    if (nSide == ENV_SIDE_A) {
        LOG(INFO) << "detect ENV_SIDE_A"<< std::endl;
        plate_detect(left_cam_img);
        lines_detect(left_cam_img, ENV_SIDE_A);
        people_detect(right_cam_img, people_right_rect);
    }
    else if (nSide == ENV_SIDE_B) {
        LOG(INFO) << "detect ENV_SIDE_B" << std::endl;
        plate_detect(right_cam_img);
        lines_detect(left_cam_img, ENV_SIDE_B);
        people_detect(left_cam_img, people_left_rect);
    }

    //debug
    info.people = 0;
    return prase_info(nSide);
}

void Env_checker::set_info_img_err()
{
    info.left_line = -1;
    info.right_line = -1;
    info.people = -1;
}

void Env_checker::plate_detect(Mat img)
{
    //plate detect
    YoloDetection best_reslut;
    Mat leftROI = img(left_rect);
    int nRet = plate_detector.get_best_reslut(leftROI, best_reslut);
    if (-1 == nRet) {
        info.left_plate = 0;
    }
    else {
        info.left_plate = 1;
    }

    Mat rightROI = img(right_rect);
    nRet = plate_detector.get_best_reslut(rightROI, best_reslut);
    if (-1 == nRet) {
        info.right_plate = 0;
    }
    else {
        info.right_plate = 1;
    }

}

void Env_checker::people_detect(Mat img,Rect people_rect)
{
    std::vector<YoloReslut> resluts;
    std::vector<YoloReslut> people_resluts;
    people_detector.detect(img, resluts);

    people_detector.get_people_reslut(resluts, people_resluts);
    bool bPeople = false;
    for (int i = 0; i < people_resluts.size(); i++) {
        Rect rect = people_resluts[i].box;
        Rect tmp = rect & people_rect;
        if (tmp.area() > 10) {
            bPeople = true;
        }
    }
    if (bPeople) {
        info.people = 1;
    }
    else {
        info.people = 0;
    }
}

void Env_checker::lines_detect(Mat img,int side)
{
    if (ENV_SIDE_A == side) {
        line_detect(img, left_line_pts, left_line_threshold, info.left_line);
        //line_detect(img, left_back_line_pts, left_back_line_threshold, info.left_back_line);
        info.right_line = -1;
        info.right_back_line = -1;
    }
    else if (ENV_SIDE_B == side) {
        line_detect(img, right_line_pts, right_line_threshold, info.right_line);
        //line_detect(img, right_back_line_pts, right_back_line_threshold, info.right_back_line);
        info.left_line = -1;
        info.left_back_line = -1;
    }
}

void Env_checker::line_detect(Mat img, std::vector<cv::Point> pts,float threshold,int& flag)
{
    double res = line_detector.detect(img, pts);
    if (res >= threshold) {
        flag = 1;
    }
    else {
        flag = 0;
    }
}

int Env_checker::prase_info(int side)
{
    int nRet =0;
    print_env_info(info);
    if(info.people){
        nRet = ENV_CHECK_PEOPLE_ERROR;
    }else{
        if(CHARGE_LEFT_SIDE == side){
            if(info.left_line == 1 ){
                nRet = ENV_CHECK_OK;
            }else{
                nRet = ENV_CHECK_LINE_ERROR;
            }

        }else{
            if(info.right_line == 1 ){
                nRet = ENV_CHECK_OK;
            }else{
                nRet = ENV_CHECK_LINE_ERROR;
            }
        }
    }
    return nRet;
}
